package com.ld.security.common.jpa.util;


import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;

import javax.persistence.Entity;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaBuilder.In;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;


import com.ld.security.common.core.util.ReflectionUtil;
import com.ld.security.common.jpa.anno.JpaKey;
import com.ld.security.common.jpa.constant.JpaCondition;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotationUtils;



public class JpaUtil {


    public static Predicate buildSql(Object obj,Root<?> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

        Predicate where = null;

        Class clazz = obj.getClass();

        for(Field field:ReflectionUtil.getAllDeclaredFields(clazz)) {
            if(Modifier.isStatic( field.getModifiers())) {
                continue;
            }
            Predicate predicate = null;
            String key = field.getName();


            Object val = ReflectionUtil.invokeGetter(obj, key);
            if(ReflectionUtil.isNull(val)) {
                continue;
            }

            JpaKey jpaKey = field.getAnnotation(JpaKey.class);
            JpaCondition operate=jpaKey.value();

            if(val instanceof Comparable) {
                Comparable<Object> comparable =(Comparable) val ;

                switch (operate) {
                    case eq:
                        predicate = cb.equal(root.get(key), val);
                        break;
                    case le:
                        predicate = cb.lessThanOrEqualTo(root.get(key),comparable);
                        break;
                    case ge:
                        predicate = cb.greaterThanOrEqualTo(root.get(key),comparable);
                        break;
                    case gt:
                        predicate = cb.lessThan(root.get(key),comparable);
                        break;
                    case lt:
                        predicate = cb.greaterThan(root.get(key),comparable);
                    case like:
                        predicate = cb.like(root.get(key), "%"+comparable+"%");
                        break;
                    case like_left:
                        predicate = cb.like(root.get(key), "%"+comparable);
                        break;
                    case like_right:
                        predicate = cb.like(root.get(key), comparable+"%");
                        break;

                }
            }else if(val instanceof Collection){

                In<Object> in=cb.in(root.get(key));
                Collection<?> iterate=(Collection<?>) val;
                for(Object v:iterate) {
                    in.value(v);
                }
                predicate = in;

            }else {
                    predicate = buildSql(val, query.from(val.getClass()), query, cb);
            }

            if(where == null) {

                where = predicate;
            }else {
                where = cb.and(where,predicate);
            }
        }

        return where;
    }

}
